package com.github.caijh.mall.system.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Resource;
import javax.inject.Inject;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.caijh.commons.util.Strings;
import com.github.caijh.framework.data.redis.Redis;
import com.github.caijh.mall.constants.Constants;
import com.github.caijh.mall.system.dao.SystemCityDao;
import com.github.caijh.mall.system.model.SystemCity;
import com.github.caijh.mall.system.request.SystemCityListReqBody;
import com.github.caijh.mall.system.request.SystemCityRequest;
import com.github.caijh.mall.system.service.SystemCityAsyncService;
import com.github.caijh.mall.system.service.SystemCityService;
import com.github.caijh.mall.system.vo.SystemCityTreeVo;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * SystemCityServiceImpl 接口实现
 * +----------------------------------------------------------------------
 * | CRMEB [ CRMEB赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed CRMEB并不是自由软件，未经许可不能去掉CRMEB相关版权
 * +----------------------------------------------------------------------
 * | Author: CRMEB Team <admin@crmeb.com>
 * +----------------------------------------------------------------------
 */
@Service
public class SystemCityServiceImpl extends ServiceImpl<SystemCityDao, SystemCity> implements SystemCityService {

    @Resource
    private SystemCityDao dao;

    @Autowired
    private SystemCityAsyncService systemCityAsyncService;

    @Inject
    private Redis redis;

    /**
     * 列表
     *
     * @param request 请求参数
     * @return List<SystemCity>
     * @author Mr.Zhang
     * @since 2020-04-17
     */
    @Override
    public Object getList(SystemCityListReqBody request) {
        Integer pid = request.getParentId();
        List<SystemCity> list = redis.getRedisTemplate().<String, List<SystemCity>>opsForHash().get(Constants.CITY_LIST, pid);

        if (list != null) {
            return list;
        }

        list = listByParentId(pid);

        if (list == null) {
            list = Lists.newArrayList();
        }
        sync(list);
        return list;
    }

    /**
     * 根据父级id获取数据
     *
     * @param parentId integer parentId
     * @return Object
     * @author Mr.Zhang
     * @since 2020-04-17
     */
    private List<SystemCity> listByParentId(Integer parentId) {
        LambdaQueryWrapper<SystemCity> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(SystemCity::getParentId, parentId);
        lambdaQueryWrapper.in(SystemCity::getIsShow, true);
        return dao.selectList(lambdaQueryWrapper);
    }

    /**
     * 修改状态
     *
     * @param id     integer id
     * @param status boolean 状态
     * @return bool
     * @author Mr.Zhang
     * @since 2020-04-17
     */
    @Override
    public boolean updateStatus(Integer id, Boolean status) {
        SystemCity systemCity = getById(id);
        systemCity.setIsShow(status);
        boolean result = updateById(systemCity);
        this.sync(Collections.singletonList(systemCity));
        return result;
    }

    /**
     * 修改城市
     *
     * @param id      integer id
     * @param request 修改参数
     * @return bool
     * @author Mr.Zhang
     * @since 2020-04-17
     */
    @Override
    public boolean update(Integer id, SystemCityRequest request) {
        SystemCity systemCity = new SystemCity();
        BeanUtils.copyProperties(request, systemCity);
        systemCity.setId(id);
        boolean result = updateById(systemCity);
        this.sync(Collections.singletonList(systemCity));
        return result;
    }

    @Override
    public String getStringNameInId(String cityIdList) {
        LambdaQueryWrapper<SystemCity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(SystemCity::getCityId, SystemCity::getName);
        lambdaQueryWrapper.in(SystemCity::getCityId, Strings.toIntListByComma(cityIdList));
        lambdaQueryWrapper.eq(SystemCity::getIsShow, true);
        List<SystemCity> systemCityList = dao.selectList(lambdaQueryWrapper);

        ArrayList<String> nameList = new ArrayList<>();
        for (SystemCity systemCity : systemCityList) {
            nameList.add(systemCity.getName());
        }
        return StringUtils.join(nameList, ",");
    }

    /**
     * 获取所有城市cityId
     *
     * @return List<Integer>
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    @Override
    public List<Integer> getCityIdList() {
        List<Integer> cityIds = redis.getList(Constants.CITY_LIST_LEVEL_1);
        if (cityIds == null) {
            LambdaQueryWrapper<SystemCity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.select(SystemCity::getCityId);
            lambdaQueryWrapper.eq(SystemCity::getLevel, 1);
            lambdaQueryWrapper.eq(SystemCity::getIsShow, true);
            List<SystemCity> systemCityList = dao.selectList(lambdaQueryWrapper);
            cityIds = systemCityList.stream().map(SystemCity::getCityId).distinct().collect(Collectors.toList());
            redis.setList(Constants.CITY_LIST_LEVEL_1, cityIds, 60 * 10L);
        }
        return cityIds;
    }

    /**
     * 根据city_id获取城市信息
     *
     * @author Mr.Zhang
     * @since 2020-05-18
     */
    @Override
    public SystemCity getCityByCityId(Integer cityId) {
        LambdaQueryWrapper<SystemCity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SystemCity::getCityId, cityId).eq(SystemCity::getIsShow, 1);
        return getOne(lambdaQueryWrapper);
    }

    @Override
    public List<SystemCityTreeVo> tree() {
        List<SystemCityTreeVo> tree = redis.get(Constants.CITY_LIST_TREE);
        if (tree != null) {
            return tree;
        }

        return systemCityAsyncService.cityTree();
    }


    @Override
    public void sync(@Nonnull List<SystemCity> list) {
        Integer pid = list.get(0).getParentId();
        redis.getRedisTemplate().opsForHash().put(Constants.CITY_LIST, pid.toString(), list);
    }

}

